import random

import pygame


# 屏幕常量定义
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
# 屏幕矩形，坐标为(0, 0)，宽为SCREEN_WIDTH，高为SCREEN_HEIGHT
SCREEN_RECT = pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)

# 刷新频率，即每秒刷新帧数，数值越高，帧数越多
FPS = 60

# 敌机速度的最小值
ENEMY_SPEED_MIN = 1
# 敌机速度的最大值
ENEMY_SPEED_MAX = 3

# 创建敌机的定时器常量
CREATE_ENEMY_EVENT = pygame.USEREVENT + 1

# 飞机子弹定时器常量
PLANE_SHOOT_EVENT = pygame.USEREVENT + 2

# 背景图片路径
BACKGROUND_IMAGE_PATH = "./airplane-wars/images/background.png"

# 敌机图片路径
ENEMY_IMAGE_PATHS = [
    "./airplane-wars/images/enemy1.png",
    "./airplane-wars/images/enemy2.png",
]

# 飞机图片路径
PLANE_IMAGE_PATH = "./airplane-wars/images/me1.png"

# 飞机子弹图片路径
PLANE_BULLET_IMAGE_PATH = "./airplane-wars/images/bullet1.png"

# 飞机距离屏幕底部的距离，数值越小，飞机越靠近屏幕底部
PLANE_BOTTOM_DISTANCE = 30


# 飞机大战游戏精灵类，作为游戏精灵的基类
# 所有精灵都继承自该类，本身继承了pygame.sprite.Sprite类，pygame.sprite.Sprite这个类是pygame提供的精灵类，提供了很多精灵相关的功能
class GameSprite(pygame.sprite.Sprite):
    def __init__(self, image_name, speed=1):
        super().__init__()
        # 加载图片，子类调用后，会自动调用父类的__init__方法，并设置self.image和self.rect和self.speed属性
        self.image = pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):
        """更新飞机位置 y坐标"""
        # 飞机垂直方向移动，速度为self.speed，speed为正值表示向下移动，负值表示向上移动
        self.rect.y += self.speed

# 背景精灵类
class Background(GameSprite):
    def __init__(self, is_alt=False):
        super().__init__(image_name=BACKGROUND_IMAGE_PATH)

        if is_alt:
            # 加载另一张背景图片，并设置图片位置为之前背景图片的顶部（y值为负的图片高度），实现循环滚动
            self.rect.y = -self.rect.height

    def update(self):
        super().update()

        # 背景图片滚动到底部后，重置图片位置为顶部
        if self.rect.y >= SCREEN_RECT.height:
            self.rect.y = -self.rect.height

# 敌机精灵类
class Enemy(GameSprite):
    def __init__(self):
        super().__init__(image_name=ENEMY_IMAGE_PATHS[0])

        # 随机设置敌机出现的位置，在x轴上随机，随机的范围在 0 ～ 屏幕宽度减去敌机图片宽度之间
        self.rect.x = random.randint(0, SCREEN_RECT.width - self.rect.width)
        # self.rect.y = -self.rect.height
        # y轴方向上从屏幕顶部缓缓下降，实现敌机从屏幕顶部缓缓出现，y轴坐标就是负的敌机图片高度
        self.rect.bottom = 0 # 等效于self.rect.y = -self.rect.height

        # 随机设置敌机的速度，速度的范围在 ENEMY_SPEED_MIN ～ ENEMY_SPEED_MAX 之间，数值越大，敌机出现后在垂直方向移动的速度越快
        self.speed = random.randint(ENEMY_SPEED_MIN, ENEMY_SPEED_MAX)



    def update(self):
        # 敌机垂直方向移动
        super().update()

        # 敌机超出屏幕后，从敌机精灵组删除
        if self.rect.y > SCREEN_RECT.height:
            self.kill()

    def __del__(self):
        print("敌机被销毁")

# 飞机精灵类
class Plane(GameSprite):
    def __init__(self):
        super().__init__(image_name=PLANE_IMAGE_PATH, speed=0)

        # 飞机初始位置，x轴方向居中，y轴方向距离屏幕底部一定的像素
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom - PLANE_BOTTOM_DISTANCE

        # 飞机子弹列表(创建子弹的精灵组)
        self.bullets = pygame.sprite.Group()

    def update(self):
        # 这里不能调用父类的update方法，因为飞机的移动是水平方向的，而父类的update方法是垂直方向的，需要完全重写实现

        # 飞机边界检测
        if self.rect.x < 0:
            self.rect.x = 0
        elif self.rect.right > SCREEN_RECT.right:
            self.rect.right = SCREEN_RECT.right

        # 飞机水平方向移动
        self.rect.x += self.speed

    def shoot(self):
        # 一次发射三颗子弹
        for i in (0, 1, 2):
            # 创建子弹精灵
            bullet = PlaneBullet()
            # 设置子弹位置
            bullet.rect.bottom = self.rect.y - i * 20
            bullet.rect.centerx = self.rect.centerx
            # 将子弹精灵添加到飞机子弹列表
            self.bullets.add(bullet)

# 飞机子弹精灵类
class PlaneBullet(GameSprite):
        def __init__(self):
            # 调用父类的__init__方法，并设置子弹的速度为-2，表示向上移动
            super().__init__(image_name=PLANE_BULLET_IMAGE_PATH, speed=-2)

        def update(self):
            super().update()

            # 飞机子弹超出屏幕后，从精灵组删除
            if self.rect.bottom < 0:
                self.kill()

        def __del__(self):
            print("飞机子弹被销毁")
    